﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.Xml.XPath;

namespace SharePointClient
{
    /// <summary>
    /// FieldCollection is an ordered View of the Fields (Columns) in a Sharepoint-List or Library
    /// </summary>
    public class FieldCollection:IDisposable,IEnumerable<Field>
    {
        public class FieldCollectionEnumerator : IEnumerator<Field>
        {
            FieldCollection col;
            int pos = -1;
            public FieldCollectionEnumerator(FieldCollection f)
            {
                pos = 0;
                col = f;
            }

            #region IEnumerator<Field> Member

            public Field Current
            {
                get { return col[pos]; }
            }

            #endregion

            #region IDisposable Member

            public void Dispose()
            {
                col=null;
            }

            #endregion

            #region IEnumerator Member

            object System.Collections.IEnumerator.Current
            {
                get { return col[pos]; }
            }

            public bool MoveNext()
            {
                return pos++ < col.Count ;
            }

            public void Reset()
            {
                pos = -1;
            }

            #endregion
        }
        private Field[] fields;
        private Dictionary<string, int> bycolname = new Dictionary<string, int>();
        private Dictionary<Guid, int> byguid = new Dictionary<Guid, int>();
        private Dictionary<string, int> byname = new Dictionary<string, int>();

        /// <summary>
        /// Create a new FieldCollection by XmlData from Sharepoint-List
        /// </summary>
        /// <param name="fields">XmlData /List/Fields </param>
        public FieldCollection(XmlNode fields)
        {
            XmlNodeList filter=WSSBase.Select(fields,"//wss:Field");
            this.fields = new Field[filter.Count];
            for (int i=0;i<filter.Count;i++)
            {
                Field f = new Field(filter[i]);
                this.fields[i] = f;

                if (f.Guid != Guid.Empty)
                {
                    byguid.Add(f.Guid, i);
                    if (f.Name != "") bycolname.Add(f.Name.Replace("_x0020_", " "), i);
                    if (f.Name != "") byname.Add(f.Name, i);
                }
            }
        }
        /// <summary>
        /// Count of Columns
        /// </summary>
        public int Count { get { return fields.Length; } }

        /// <summary>
        /// Get Field by occurence in XML
        /// </summary>
        /// <param name="pos">Position of Column</param>
        /// <returns>Field</returns>
        public Field this[int pos]
        {
            get { return fields[pos]; }
        }
        /// <summary>
        /// Get Field by Name (both Names are possible (See Field.ColumnName and Field.Name)
        /// </summary>
        /// <param name="name">Column Name</param>
        /// <returns>Field</returns>
        public Field this[string name]
        {
            get {  if (bycolname.ContainsKey(name)) return fields[bycolname[name]];else if (byname.ContainsKey(name)) return fields[byname[name]]; else return null; }
        }
        /// <summary>
        /// Return Field by Identity
        /// </summary>
        /// <param name="id">Guid</param>
        /// <returns>Field if found or null if not</returns>
        public Field this[Guid id]
        {
            get { if (byguid.ContainsKey(id)) return fields[byguid[id]]; else return null; }
        }
        
        #region IDisposable Member

        /// <summary>
        /// End of FieldCollection
        /// </summary>
        public void Dispose()
        {
            foreach (Field f in fields) f.Dispose();
        }

        #endregion

        #region IEnumerable<Field> Member

        public IEnumerator<Field> GetEnumerator()
        {
            return new FieldCollectionEnumerator(this) ;
        }

        #endregion

        #region IEnumerable Member

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new FieldCollectionEnumerator(this);
        }

        #endregion
    }
}
